package com.mayisoftware.mayioa.common.impl.utils.bean;

import org.springframework.util.ReflectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;


/**
 * 反射工具类
 */
public class ReflectionUtil extends ReflectionUtils {

    /**	getFields()获得某个类的所有的公共（public）的字段，包括父类。
     getDeclaredFields()获得某个类的所有申明的字段，即包括public、private和proteced，但是不包括父类的申明字段。
     同样类似的还有getConstructors()和getDeclaredConstructors()，getMethods()和getDeclaredMethods()
     */
    /**
     * 获取类所有的属性(包括从父类继承的)
     *
     * @param clazz
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static Field[] getAllDeclareFields(Class clazz){
        if (clazz.getSuperclass() == Object.class) {//父类就是顶级类
            return clazz.getDeclaredFields();
        }

        Set<String> names = new HashSet<String>();
        List<Field> list = new ArrayList<Field>();
        Class<?> searchType = clazz;
        while (!Object.class.equals(searchType) && searchType != null) {
            Field[] fields = searchType.getDeclaredFields();
            for (Field field : fields) {
                if (names.contains(field.getName())) {
                    continue;
                }
                list.add(field);//字段属性
            }
            searchType = searchType.getSuperclass();//父类
        }
        //把list转化为数组形式返回
        Field[] fields = new Field[list.size()];
        return list.toArray(fields);

    }
    /**
     * 判断某字符串是否为空或长度为0或由空白符(whitespace) 构成
     *
     * @param cs
     * @return
     */
    public static boolean isBlank(final CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (Character.isWhitespace(cs.charAt(i)) == false) {
                return false;
            }
        }
        return true;
    }

    /**
     * 直接通过反射获取对象属性的值
     *
     * @param target
     * @param fieldName
     * @return
     */
    public static Object getFieldValue(Object target, String fieldName) {
        if (target == null) {
            return null;
        }
        if (isBlank(fieldName)) {
            return null;
        }
        //Map直接返回
        if (target instanceof Map) {
            return ((Map<?, ?>) target).get(fieldName);
        }
        Class<?> clazz = null;
        if (target instanceof Class) {
            clazz = (Class<?>) target;
        }else {
            clazz = target.getClass();
        }

        Map<String, Field> fieldMap = null;

        synchronized (clazz) {
            Field field = findField(clazz, fieldName);
            if (field != null) {
                field.setAccessible(true);
                fieldMap = new ConcurrentHashMap<String, Field>();
                fieldMap.put(fieldName,field);
            }
     }


        if(fieldMap == null || !fieldMap.containsKey(fieldName)){
            throw new RuntimeException(String.format("类 [%s] 不存在属性 [%s]", clazz.getCanonicalName(), fieldName));
        }

        Field filed = fieldMap.get(fieldName);

        try {
            return filed.get(target);
        } catch (Exception e) {
            String message = String.format("类 [%s] 反射访问属性 [%s] 异常!", clazz.getCanonicalName(), fieldName);
            throw new RuntimeException(message, e);
        }

    }

    /**
     * 直接通过反射设置对象属性的值
     * @param target
     * @param fieldName
     * @param fieldValue
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void setFieldValue(Object target, String fieldName, Object fieldValue){

        if(target == null || isBlank(fieldName)){
            return;
        }
        //map直接返回
        if(target instanceof Map){
            ((Map)target).put(fieldName, fieldValue);
            return;
        }

        Class<?> clazz = null;
        if(target instanceof Class){
            clazz = (Class<?>)target;
        } else {
            clazz = target.getClass();
        }

        Map<String, Field> filedMap = null;
        //没有属性
        if(filedMap == null || !filedMap.containsKey(fieldName)){

            synchronized (clazz) {
                Field field = findField(clazz, fieldName);
                if(field != null){
                    field.setAccessible(true);
                    if(filedMap == null){
                        filedMap = new ConcurrentHashMap<String, Field>();//做个长度缓存
                        filedMap.put(fieldName, field);
                    }
                }
            }
        }

        if(filedMap == null || !filedMap.containsKey(fieldName)){
            throw new RuntimeException(String.format("类 [%s] 不存在属性 [%s]", clazz.getCanonicalName(), fieldName));
        }

        Field filed = filedMap.get(fieldName);

        try {
            filed.set(target, fieldValue);
        } catch (Exception e) {
            String message = String.format("类 [%s] 反射访问属性 [%s] 异常!", clazz.getCanonicalName(), fieldName);
            throw new RuntimeException(message, e);
        }
    }

}
